﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;
using Utility;
using System.Text.RegularExpressions;
using System.Threading;

namespace Client
{
    public partial class frmNhapTen : Form
    {
        struct Server
        {
            public IPAddress IP;
            public int Online;
        }
        public TcpClient client;
        private UdpClient udpClient;
        public string UserName { get; private set; }
        private byte[] clientBuff;
        IPEndPoint udpServerEP = new IPEndPoint(IPAddress.Broadcast, 2223);

        private List<Server> ListServer ;

        public frmNhapTen()
        {
            InitializeComponent();
        }

        private void frmNhapTen_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
          
            DiemDanh();
        }

        void DiemDanh()
        {
            ListServer = new List<Server>();
            udpClient = new UdpClient();
            var strFind = "Find IP";
            udpClient.BeginSend(Encoding.UTF8.GetBytes(strFind), strFind.Length, udpServerEP, UdpSendCallback, null);

            var timKiemMayChu = new Action(TimKiemMayChu);
            timKiemMayChu.BeginInvoke(TimMayChu, timKiemMayChu);
        }

        private void TimMayChu(IAsyncResult ar)
        {
            (ar.AsyncState as Action).EndInvoke(ar);
        }

        void TimKiemMayChu()
        {
            Thread.Sleep(1000);
            if (ListServer.Count == 0) //không có máy chủ nào trả lời
            {
                MessageBox.Show("Không tìm thấy máy chủ, bạn hãy khỏi động 1 máy chủ!");
            }
            else
            {
                var source = from server in ListServer
                             orderby server.Online descending
                             select new { IP = server.IP, Text = string.Format("{0} ({1} online)", server.IP, server.Online) };
                cmbServer.DataSource = source.ToList();
                cmbServer.DisplayMember = "Text";
                cmbServer.ValueMember = "IP";
            }
        }

        void UdpSendCallback(IAsyncResult ar)
        {
            udpClient.EndSend(ar);
            udpClient.BeginReceive(UDPReceiveCallback, null);
        }

        private void UDPReceiveCallback(IAsyncResult ar)
        {
            IPEndPoint serverEP = new IPEndPoint(IPAddress.Any, 0);
            var data = udpClient.EndReceive(ar, ref serverEP);
            var sv = new Server()
                {
                    IP = serverEP.Address,
                    Online = BitConverter.ToInt32(data, 0)
                };
            lock ("ListServer")
            {
                ListServer.Add(sv);
            }
            udpClient.BeginReceive(UDPReceiveCallback, null);
        }


        private void btnChapNhan_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(txtTen.Text))
                {
                    MessageBox.Show("Bạn chưa nhập tên!!!");
                    return;
                }
                var part = @"^[a-z0-9 ]+$";
                var m = Regex.Match(txtTen.Text, part, RegexOptions.IgnoreCase);

                if (m.Success)
                {
                    var ipe = new IPEndPoint(IPAddress.Parse(cmbServer.SelectedValue.ToString()), 2222);
                    client = new TcpClient();
                    client.Connect(ipe);

                    var netStream = client.GetStream();
                    var msg = new ChessMessage()
                    {
                        SenderName = txtTen.Text,
                        Type = ChessMessageType.Login
                    };
                    var buff = msg.ToByteArray();
                    netStream.BeginWrite(buff, 0, buff.Length, OnWrite, netStream);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        void OnWrite(IAsyncResult ar)
        {
            var stream = ar.AsyncState as NetworkStream;
            stream.EndWrite(ar);

            clientBuff = new byte[1024];
            stream.BeginRead(clientBuff, 0, clientBuff.Length, OnRead, stream);
        }


        void OnRead(IAsyncResult ar)
        {
            var stream = ar.AsyncState as NetworkStream;
            stream.EndRead(ar);
            var msg = new ChessMessage(clientBuff);
            switch (msg.Type)
            {
                case ChessMessageType.Logout:
                    MessageBox.Show("Tên đăng nhập này đã tồn tại!");
                    break;
                case ChessMessageType.Login:
                    UserName = txtTen.Text;
                    this.DialogResult = DialogResult.OK;
                    break;
            }
        }

        private void btnHuy_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
        }

        private void button1_Click(object sender, EventArgs e)
        {

            DiemDanh();
        }
    }
}
